import calendar
import math
import random
import string
from datetime import datetime, timedelta, time

import pandas as pd


def random_string(count=20, letters=True, numbers=False):
    if count <= 0:
        count = 20

    char_pool = ""

    if letters:
        char_pool += string.ascii_letters  # 包含所有字母
    if numbers:
        char_pool += string.digits  # 包含数字

    if not char_pool:  # 如果没有字母和数字
        char_pool = "".join(
            chr(i) for i in range(0, 0x110000)
        )  # 包含所有 Unicode 字符

    buffer = []

    while count > 0:
        ch = random.choice(char_pool)  # 随机选择字符
        buffer.append(ch)
        count -= 1

    return "".join(buffer)


def random_time():
    hour = random.randint(0, 23)
    minute = random.randint(0, 59)
    second = random.randint(0, 59)
    return time(hour, minute, second).strftime('%H:%M:%S')


def render_template(template_str, data):
    class SafeTemplate(string.Template):
        def substitute(self, mapping):
            safe_mapping = {}
            for k, v in mapping.items():
                if v is None:
                    safe_mapping[k] = 'null'
                elif isinstance(v, datetime):
                    safe_mapping[k] = f"to_date('{v.strftime('%Y-%m-%d %H:%M:%S')}', 'yyyy-mm-dd hh24:mi:ss')"
                elif isinstance(v, str):
                    if v.startswith("to_date"):
                        safe_mapping[k] = v
                    else:
                        safe_mapping[k] = f"'{v}'"
                elif isinstance(v, float):
                    if math.isnan(v):
                        safe_mapping[k] = 'null'
                    else:
                        safe_mapping[k] = v
                else:
                    safe_mapping[k] = v
            return super().substitute(safe_mapping)

    template = SafeTemplate(' '.join(map(lambda x: x.strip(), template_str.splitlines())))
    sql = template.substitute(data).strip()
    if not sql.endswith(';'):
        sql += ';'
    if not sql.endswith('\n'):
        sql += '\n'
    return sql


holidays_array = [
    "2024-01-01",  # 元旦
    "2024-01-20",  # 春节
    "2024-01-21",  # 春节
    "2024-01-22",  # 春节
    "2024-01-23",  # 春节
    "2024-01-24",  # 春节
    "2024-01-25",  # 春节
    "2024-01-26",  # 春节
    "2024-02-10",  # 元宵节
    "2024-04-04",  # 清明节
    "2024-05-01",  # 劳动节
    "2024-06-10",  # 端午节
    "2024-09-17",  # 中秋节
    "2024-10-01",  # 国庆节
    "2024-10-02",  # 国庆节
    "2024-10-03",  # 国庆节
    "2024-10-04",  # 国庆节
    "2024-10-05",  # 国庆节
    "2024-10-06",  # 国庆节
    "2024-10-07",  # 国庆节
]


def getNoneHoliday():
    # 将节假日字符串转换为日期对象
    holidays = set(datetime.strptime(date, "%Y-%m-%d").date() for date in holidays_array)

    # 获取2024年每周的两个非节假日、非周六和周日的日期
    non_holiday_weekdays = {}

    # 遍历每个月
    for month in range(1, 13):  # 修改为 1 至 12 以包含整个年
        # 获取该月的天数
        num_days = calendar.monthrange(2024, month)[1]
        non_holiday_days = []

        for day in range(1, num_days + 1):
            date = datetime(2024, month, day).date()
            # 检查是否是工作日且不是节假日
            if (
                    date.weekday() < 5 and date not in holidays
            ):  # weekday() < 5 表示周一到周五
                # 格式化为 yyyy-mm-dd
                formatted_date = date.strftime("%Y-%m-%d")
                non_holiday_days.append(formatted_date)

        # 每周最多取两个非假日
        # week_days = []
        # for i in range(0, len(non_holiday_days), 2):  # 每三天取一次
        #     week_days.append(non_holiday_days[i])  # 仅取每周的两个非假日

        if non_holiday_days:
            non_holiday_weekdays[calendar.month_name[month]] = non_holiday_days

    return non_holiday_weekdays


def generate_workdays(start_date_str, end_date_str, spans=1):
    holidays = map(lambda x: datetime.strptime(x, "%Y-%m-%d").date(), holidays_array)

    start_date = datetime.strptime(start_date_str, '%Y-%m-%d')
    end_date = datetime.strptime(end_date_str, '%Y-%m-%d')
    workdays = []
    current_date = start_date

    while current_date < end_date:
        if current_date.weekday() < 5 and workdays not in holidays:  # 0-4 表示周一到周五
            workdays.append(current_date.strftime('%Y-%m-%d') + ' ' + random_time())
        current_date += timedelta(days=spans)
    return workdays


def generate_day(start_date_str, end_date_str, spans=1):
    start_date = datetime.strptime(start_date_str, '%Y-%m-%d')
    end_date = datetime.strptime(end_date_str, '%Y-%m-%d')
    workdays = []
    current_date = start_date

    while current_date < end_date:
        if current_date.weekday() < 5:  # 0-4 表示周一到周五
            workdays.append(current_date.strftime('%Y-%m-%d') + ' ' + '00:00:00')
        current_date += timedelta(days=spans)
    return workdays


def get_random_date_str(start_date_str, minutes=4):
    start_date, end_date = get_random_date(start_date_str, minutes=minutes)
    end_date_str = datetime.strftime(end_date, '%Y-%m-%d %H:%M:%S')
    return f"to_date('{start_date_str}', 'yyyy-mm-dd hh24:mi:ss')", f"to_date('{end_date_str}', 'yyyy-mm-dd hh24:mi:ss')"


def get_random_date(start_date, minutes=4):
    start_date = datetime.strptime(start_date, '%Y-%m-%d %H:%M:%S')
    end_date = start_date + timedelta(minutes=minutes)
    return start_date, end_date


def read_sql_file(file_path, trans=lambda x: x):
    result = []
    sql_stmt = ''
    for line in open(file_path, encoding='utf-8'):
        if not line:
            continue
        sql_stmt += line
        if sql_stmt.strip().endswith(";"):
            result.append(trans(sql_stmt))
            sql_stmt = ''
    return result


def write_file(file_path, content):
    file_path = '/Users/lujiewen/asiainfo-sec/fujian-data/' + file_path
    with open(file_path, 'w', encoding='utf-8') as file:
        file.writelines(content)


def read_excel(file_path):
    file_path = '/Users/lujiewen/asiainfo-sec/fujian-data/' + file_path
    df = pd.read_excel(file_path)
    return df


if __name__ == '__main__':
    span = generate_workdays('2024-01-01', '2024-12-31', 6)
    print(len(span))
